import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import { ComponentDataStore } from '@/config/component-data';

/**
 * 工具函数集合
 * 提供各种辅助功能，如路径处理、文件操作、字符串处理等
 */

/**
 * 获取当前工作区根路径
 * @returns 工作区根路径字符串，如果没有工作区则返回 undefined
 */
export function getWorkspaceRoot(): string | undefined {
    const workspaceFolders = vscode.workspace.workspaceFolders;
    return workspaceFolders ? workspaceFolders[0].uri.fsPath : undefined;
}

/**
 * 获取扩展的安装路径
 * @param context 扩展上下文
 * @returns 扩展安装路径
 */
export function getExtensionPath(context: vscode.ExtensionContext): string {
    return context.extensionPath;
}

/**
 * 检查文件是否包含特定导入语句
 * @param document 文本文档
 * @param importPath 要检查的导入路径
 * @returns 是否包含该导入
 */
export function hasImportStatement(document: vscode.TextDocument, importPath: string): boolean {
    const text = document.getText();
    const regex = new RegExp(`from\\s+['"]${escapeRegExp(importPath)}['"]`);
    return regex.test(text);
}

/**
 * 转义正则表达式特殊字符
 * @param string 要转义的字符串
 * @returns 转义后的字符串
 */
export function escapeRegExp(string: string): string {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

/**
 * 获取光标位置的上下文信息
 * @param document 文本文档
 * @param position 光标位置
 * @returns 上下文信息对象
 */
export function getCursorContext(document: vscode.TextDocument, position: vscode.Position): {
    isJsx: boolean;
    isInsideTag: boolean;
    currentWord: string;
    lineText: string;
} {
    const lineText = document.lineAt(position).text;
    const textBeforeCursor = lineText.substring(0, position.character);
    
    return {
        isJsx: textBeforeCursor.includes('<') && !textBeforeCursor.includes('>'),
        isInsideTag: isInsideHtmlTag(textBeforeCursor),
        currentWord: getCurrentWord(textBeforeCursor),
        lineText: lineText
    };
}

/**
 * 检查是否在 HTML 标签内
 * @param text 文本内容
 * @returns 是否在标签内
 */
export function isInsideHtmlTag(text: string): boolean {
    const lastOpenBracket = text.lastIndexOf('<');
    const lastCloseBracket = text.lastIndexOf('>');
    return lastOpenBracket > lastCloseBracket;
}

/**
 * 获取当前单词
 * @param text 文本内容
 * @returns 当前单词
 */
export function getCurrentWord(text: string): string {
    // 匹配单词边界
    const words = text.split(/[\s<>="']+/);
    return words[words.length - 1] || '';
}

/**
 * 智能纠正组件名称大小写
 * @param inputName 输入的组件名
 * @returns 纠正后的组件名
 */
export function correctComponentCase(inputName: string): string {
    const dataStore = ComponentDataStore.getInstance();
    const component = dataStore.getComponent(inputName);
    return component ? component.name : inputName;
}

/**
 * 获取最匹配的组件名称
 * @param inputName 输入的组件名
 * @returns 最匹配的组件名或 null
 */
export function getBestComponentMatch(inputName: string): string | null {
    const dataStore = ComponentDataStore.getInstance();
    const lowerInput = inputName.toLowerCase();
    const allComponents = dataStore.getAllComponents();
    
    // 1. 精确匹配（忽略大小写）
    const exactMatch = allComponents.find(comp => 
        comp.name.toLowerCase() === lowerInput ||
        (comp.aliases && comp.aliases.includes(lowerInput))
    );
    
    if (exactMatch) {return exactMatch.name;}
    
    // 2. 包含匹配
    const containsMatch = allComponents.find(comp => 
        comp.name.toLowerCase().includes(lowerInput) ||
        (comp.aliases && comp.aliases.some(alias => alias.includes(lowerInput)))
    );
    
    if (containsMatch) {return containsMatch.name;}
    
    // 3. 模糊匹配（Levenshtein距离）
    let bestMatch = null;
    let bestScore = Infinity;
    
    for (const comp of allComponents) {
        const score = calculateSimilarity(lowerInput, comp.name.toLowerCase());
        if (score < bestScore) {
            bestScore = score;
            bestMatch = comp;
        }
        
        // 检查别名
        if (comp.aliases) {
            for (const alias of comp.aliases) {
                const aliasScore = calculateSimilarity(lowerInput, alias);
                if (aliasScore < bestScore) {
                    bestScore = aliasScore;
                    bestMatch = comp;
                }
            }
        }
    }
    
    return bestScore < 0.7 && bestMatch ? bestMatch.name : null;
}

/**
 * 计算字符串相似度（0-1之间，1表示完全相同）
 * @param s1 字符串1
 * @param s2 字符串2
 * @returns 相似度分数
 */
export function calculateSimilarity(s1: string, s2: string): number {
    if (s1 === s2) {return 0;}
    
    const longer = s1.length > s2.length ? s1 : s2;
    const shorter = s1.length > s2.length ? s2 : s1;
    
    if (longer.length === 0) {return 1.0;}
    
    return (longer.length - editDistance(longer, shorter)) / parseFloat(longer.length.toString());
}

/**
 * 计算编辑距离（Levenshtein距离）
 * @param s1 字符串1
 * @param s2 字符串2
 * @returns 编辑距离
 */
function editDistance(s1: string, s2: string): number {
    s1 = s1.toLowerCase();
    s2 = s2.toLowerCase();
    
    const costs: number[] = [];
    for (let i = 0; i <= s1.length; i++) {
        let lastValue = i;
        for (let j = 0; j <= s2.length; j++) {
            if (i === 0) {
                costs[j] = j;
            } else if (j > 0) {
                let newValue = costs[j - 1];
                if (s1.charAt(i - 1) !== s2.charAt(j - 1)) {
                    newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
                }
                costs[j - 1] = lastValue;
                lastValue = newValue;
            }
        }
        if (i > 0) {costs[s2.length] = lastValue;}
    }
    return costs[s2.length];
}

/**
 * 延迟执行函数
 * @param ms 延迟毫秒数
 * @returns Promise对象
 */
export function delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
}

/**
 * 安全执行函数，捕获异常并返回默认值
 * @param fn 要执行的函数
 * @param defaultValue 发生异常时的默认值
 * @returns 函数执行结果或默认值
 */
export async function safeExecute<T>(fn: () => Promise<T>, defaultValue: T): Promise<T> {
    try {
        return await fn();
    } catch (error) {
        console.error('安全执行函数出错:', error);
        return defaultValue;
    }
}

/**
 * 创建唯一的ID
 * @param length ID长度
 * @returns 唯一ID字符串
 */
export function createUniqueId(length: number = 8): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
}

/**
 * 深度合并对象
 * @param target 目标对象
 * @param source 源对象
 * @returns 合并后的对象
 */
export function deepMerge<T extends object>(target: T, source: Partial<T>): T {
    const result = { ...target };
    
    for (const key in source) {
        if (source.hasOwnProperty(key)) {
            const targetValue = target[key];
            const sourceValue = source[key];
            
            if (isObject(targetValue) && isObject(sourceValue)) {
                result[key as keyof T] = deepMerge(targetValue, sourceValue as any);
            } else if (sourceValue !== undefined) {
                result[key as keyof T] = sourceValue as T[keyof T];
            }
        }
    }
    
    return result;
}

/**
 * 检查是否为对象
 * @param obj 要检查的值
 * @returns 是否为对象
 */
export function isObject(obj: any): obj is object {
    return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
}

/**
 * 将字符串转换为驼峰命名
 * @param str 输入字符串
 * @returns 驼峰命名字符串
 */
export function toCamelCase(str: string): string {
    return str
        .replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
        .replace(/^(.)/, (c) => c.toLowerCase());
}

/**
 * 将字符串转换为帕斯卡命名（大驼峰）
 * @param str 输入字符串
 * @returns 帕斯卡命名字符串
 */
export function toPascalCase(str: string): string {
    return str
        .replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
        .replace(/^(.)/, (c) => c.toUpperCase());
}

/**
 * 将字符串转换为短横线命名（kebab-case）
 * @param str 输入字符串
 * @returns 短横线命名字符串
 */
export function toKebabCase(str: string): string {
    return str
        .replace(/([a-z])([A-Z])/g, '$1-$2')
        .replace(/[\s_]+/g, '-')
        .toLowerCase();
}

/**
 * 格式化文件大小
 * @param bytes 字节数
 * @returns 格式化后的文件大小字符串
 */
export function formatFileSize(bytes: number): string {
    if (bytes === 0) {return '0 B';}
    
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

/**
 * 检查路径是否存在
 * @param filePath 文件路径
 * @returns 是否存在
 */
export async function pathExists(filePath: string): Promise<boolean> {
    try {
        await fs.promises.access(filePath);
        return true;
    } catch {
        return false;
    }
}

/**
 * 递归创建目录
 * @param dirPath 目录路径
 * @returns 是否创建成功
 */
export async function ensureDirectoryExists(dirPath: string): Promise<boolean> {
    try {
        await fs.promises.mkdir(dirPath, { recursive: true });
        return true;
    } catch (error) {
        console.error(`创建目录失败: ${dirPath}`, error);
        return false;
    }
}

/**
 * 读取JSON文件
 * @param filePath 文件路径
 * @returns 解析后的JSON对象或null
 */
export async function readJsonFile<T>(filePath: string): Promise<T | null> {
    try {
        const content = await fs.promises.readFile(filePath, 'utf-8');
        return JSON.parse(content) as T;
    } catch (error) {
        console.error(`读取JSON文件失败: ${filePath}`, error);
        return null;
    }
}

/**
 * 写入JSON文件
 * @param filePath 文件路径
 * @param data 要写入的数据
 * @param indent 缩进空格数
 * @returns 是否写入成功
 */
export async function writeJsonFile(filePath: string, data: any, indent: number = 2): Promise<boolean> {
    try {
        const content = JSON.stringify(data, null, indent);
        await fs.promises.writeFile(filePath, content, 'utf-8');
        return true;
    } catch (error) {
        console.error(`写入JSON文件失败: ${filePath}`, error);
        return false;
    }
}

/**
 * 获取文件扩展名
 * @param fileName 文件名
 * @returns 文件扩展名
 */
export function getFileExtension(fileName: string): string {
    return path.extname(fileName).toLowerCase();
}

/**
 * 获取文件名（不含扩展名）
 * @param fileName 文件名
 * @returns 不含扩展名的文件名
 */
export function getFileNameWithoutExtension(fileName: string): string {
    return path.basename(fileName, path.extname(fileName));
}

/**
 * 显示信息提示
 * @param message 消息内容
 * @param type 消息类型
 */
export function showMessage(message: string, type: 'info' | 'warning' | 'error' = 'info'): void {
    switch (type) {
        case 'info':
            vscode.window.showInformationMessage(message);
            break;
        case 'warning':
            vscode.window.showWarningMessage(message);
            break;
        case 'error':
            vscode.window.showErrorMessage(message);
            break;
    }
}

/**
 * 显示选择对话框
 * @param items 选项列表
 * @param placeHolder 提示文本
 * @returns 选择的项目或undefined
 */
export async function showQuickPick<T extends vscode.QuickPickItem>(items: T[], placeHolder: string): Promise<T | undefined> {
    return await vscode.window.showQuickPick(items, {
        placeHolder: placeHolder,
        matchOnDetail: true,
        matchOnDescription: true
    });
}

/**
 * 显示输入框
 * @param prompt 提示文本
 * @param placeHolder 占位符
 * @param value 默认值
 * @returns 输入的值或undefined
 */
export async function showInputBox(prompt: string, placeHolder: string = '', value: string = ''): Promise<string | undefined> {
    return await vscode.window.showInputBox({
        prompt,
        placeHolder,
        value
    });
}

/**
 * 日志记录器
 */
export class Logger {
    private static outputChannel: vscode.OutputChannel;

    static initialize(channelName: string = 'Component Completion') {
        if (!this.outputChannel) {
            this.outputChannel = vscode.window.createOutputChannel(channelName);
        }
    }

    static log(message: string, level: 'info' | 'warn' | 'error' = 'info') {
        if (!this.outputChannel) {
            this.initialize();
        }

        const timestamp = new Date().toISOString();
        const formattedMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`;

        this.outputChannel.appendLine(formattedMessage);

        // 错误级别同时显示在界面上
        if (level === 'error') {
            vscode.window.showErrorMessage(message);
        } else if (level === 'warn') {
            vscode.window.showWarningMessage(message);
        }
    }

    static show() {
        if (this.outputChannel) {
            this.outputChannel.show();
        }
    }

    static dispose() {
        if (this.outputChannel) {
            this.outputChannel.dispose();
        }
    }
}